// 用于创建 组件右侧工具 实例
function createBlock({
  style,
  attribute,
  event,
  state
}) {
  this.defaultStyle = {
    width: '20px',
    height: '20px',
    cursor: 'pointer',
    padding: '5px 0 0 5px',
    display: 'block'
  }
  this.style = {
    ...this.defaultStyle,
    ...style
  }
  this.attribute = attribute
  this.event = event
  this.img = document.createElement('img')
  this.state = state
}

const cellCount = {}

createBlock.prototype.setStyle = function () {
  for (const key in this.style) {
    this.img.style[key] = this.style[key]
  }
}
createBlock.prototype.setAttribute = function () {
  for (const key in this.attribute) {
    this.img.setAttribute(key, this.attribute[key])
  }
}
createBlock.prototype.setEvent = function () {
  for (const key in this.event) {
    mxEvent.addListener(this.img, key,
      mxUtils.bind(this, function (evt) {
        this.event[key](evt, this.state)
      })
    );
  }
}

createBlock.prototype.init = function () {
  this.setStyle()
  this.setAttribute()
  this.setEvent()
  return this.img
}

// 动态设置端口的相对位置
function autoPosition(state, cell, blockWidh, blockHeight) {
  const children = cell.children || []
  const {
    width,
    height
  } = cell.geometry

  // 找到边对应的端口list 按照位置进行排序
  const top = children.filter(i => i.geometry.y * height < blockHeight).sort((a, b) => a.geometry.x - b.geometry.x)
  const right = children.filter(i => i.geometry.x * width > width - i.geometry.width - blockWidh).sort((a, b) => a.geometry.y - b.geometry.y)
  const bottom = children.filter(i => i.geometry.y * height > height - i.geometry.height - blockHeight).sort((a, b) => a.geometry.x - b.geometry.x)
  const left = children.filter(i => i.geometry.x * width < blockWidh).sort((a, b) => a.geometry.y - b.geometry.y)

  // 找最长的边----------------
  const spaceObject = {
    position: '',
    point: [0, 0],
    space: 0,
    centerPoint: 0
  }
  const getClient = (start, end, position) => {
    if ((end - start) > spaceObject.space) {
      spaceObject.position = position
      spaceObject.point = [start, end]
      spaceObject.space = end - start
      spaceObject.centerPoint = start + spaceObject.space / 2
    }
  }
  // 上下水平方向
  const getHorizonSpace = (list, position) => {
    let beforePosition = 0
    list.forEach(cell => {
      getClient(beforePosition, cell.geometry.x * width, position)
      beforePosition = cell.geometry.x * width + cell.geometry.width
    })
    getClient(beforePosition, width, position)
  }
  // 左右垂直方向
  const getVertialSpace = (list, position) => {
    let beforePosition = 0
    list.forEach(cell => {
      getClient(beforePosition, cell.geometry.y * height, position)
      beforePosition = cell.geometry.y * height + cell.geometry.height
    })
    getClient(beforePosition, height, position)
  }
  getHorizonSpace(top, 'top')
  getVertialSpace(right, 'right')
  getHorizonSpace(bottom, 'bottom')
  getVertialSpace(left, 'left')

  if (spaceObject.space < blockWidh) {
    // 排列不下， 增加高度
    state.cell.geometry.height += blockHeight + 10
    bottom.forEach(item => {
      window.myEditor.editor.graph.removeCells([item])
      window.myEditor.editor.graph.addCells([item], state.cell);
    })
    getVertialSpace(right, 'right')
  }

  switch (spaceObject.position) {
    case 'top':
      return [spaceObject.centerPoint, 0]
    case 'right':
      return [width, spaceObject.centerPoint]
    case 'bottom':
      return [spaceObject.centerPoint, height]
    default:
      return [0, spaceObject.centerPoint]
  }
}

// 创建端口
function creatPort(state) {
  const attribute = {
    src: '../img/status/bg_box.png',
    title: '端口'
  }
  const arg = {
    attribute,
    event: {
      click: creatPort.prototype.addCell
    },
    state
  }
  const block = new createBlock(arg)
  return block.init(this)
}
creatPort.prototype.addCell = function (evt, state) {
  const port = 'SYSML_BLOCKDEFINITION_WANZHENGPORTJIEDIAN'
  const cells = Sidebar.prototype.cellAndStyleMap.filter(i => i.display === port)
  if (cellCount[state.cell.mxObjectId]) {
    cellCount[state.cell.mxObjectId]++
  } else {
    cellCount[state.cell.mxObjectId] = 1
  }
  const offset = autoPosition(state, state.cell, 10, 10)

  const clones = window.myEditor.editor.graph.cloneCells(cells[0].cells);
  let cell = window.myEditor.editor.graph.insertVertex(state.cell, clones, '', offset[0] / state.cell.geometry.width, offset[1] / state.cell.geometry.height, 10, 10);
  cell.geometry.offset = new mxPoint(-5, -5);
  cell.geometry.relative = true;
  window.myEditor.editor.graph.refresh()
}

function updateStyle(state, leave) {
  let style = state.cell.style.split(';').filter(i => !!i).reduce((pre, item) => {
    let i = item.split('=')
    if (Array.isArray(i) && i.length === 2) {
      pre[i[0]] = i[1]
    }
    return pre
  }, {})
  if (!leave) {
    style[mxConstants.STYLE_FILLCOLOR] = '#fff';
  } else {
    style[mxConstants.STYLE_FILLCOLOR] = '#dae8fc';
  }
  let styleStr = ''
  for (const key in style) {
    styleStr += `${key}=${style[key]};`
  }
  state.cell.style = styleStr
  window.myEditor.editor.graph.refresh()
};

function mianCallBack(EditorUi) {
  setTimeout(() => {
    // if(!objectXml) return
    // var objectNode = mxUtils.parseXml(objectXml).documentElement;

    function mxVertexToolHandler(state) {
      mxVertexHandler.apply(this, arguments);
    };
    mxVertexToolHandler.prototype = new mxVertexHandler();
    mxVertexToolHandler.prototype.constructor = mxVertexToolHandler;
    mxVertexToolHandler.prototype.domNode = null;
    // mxVertexToolHandler.prototype.objectList = objectNode.getElementsByTagName('model');


    mxVertexToolHandler.prototype.addCell = function (cellObject, state, graph, that) {
      const cell = graph.cloneCell(cellObject.cell)
      var node = document.createElement('a');
      node.className = 'geItem';
      node.style.cssText = 'position:relative;display:inline-block;position:relative;' +
        'width:20px;height:20px;cursor:pointer;overflow:hidden;padding:3px 0 0 3px;background-color: #fff;';
      node.title = cell.value.getAttribute('name')
      node.setAttribute('draggable', false)
      this.domNode.appendChild(node);
      EditorUi.sidebar.createThumb([cell], 25, 25, node, null, true, false, cell.geometry.width, cell.geometry.height, );

      EditorUi.sidebar.setIcon(node, cell);

      mxEvent.addGestureListeners(node,
        mxUtils.bind(that, function (evt) {

          window.isAddingStatus = true
          window.myEditor.sidebar.updateToolStatus()

          window.edgeValue = cell.value
          // 根据display获取对应的style，保存到edge中，用于连线的样式
          window.edgeValue.setAttribute('style', cellObject.style)

          window.mxConnectioCell = cell

          graph.selectingCell = cell

          var pt = mxUtils.convertPoint(graph.container,
            mxEvent.getClientX(evt), mxEvent.getClientY(evt));
          graph.connectionHandler.start(state, pt.x, pt.y);
          // window.isAddingStatus = true
          graph.isMouseDown = true;
          graph.isMouseTrigger = mxEvent.isMouseEvent(evt);
          mxEvent.consume(evt);
        })
      );
    }

    mxVertexToolHandler.prototype.createConnectIcons = function (state, graph, that, createImage) {
      if (state.cell.value && state.cell.value instanceof Object) {
        if (state.cell.value instanceof Object && window.relationRules.hasOwnProperty(state.cell.value.getAttribute('metaId'))) {
          // 能连接的线的metaId
          const cellLines = window.relationRules[state.cell.value.getAttribute('metaId')]
          if (Object.keys(cellLines).length) {
            // 能连接的线的cell
            const lines = Sidebar.prototype.cellAndStyleMap.filter(i => {
              return cellLines.hasOwnProperty(i.metaId)
            })
            if (lines.length === 0) {
              this.domNode.parentNode && this.domNode.parentNode.removeChild(this.domNode);
              this.domNode = null
            }
            lines.forEach(cellObject => {
              this.addCell(cellObject, state, graph, that)
            })
          }
        }
      }
    }

    mxVertexToolHandler.prototype.createBlockVisibleIcon = function (state, graph) {
      if (state.cell.value && state.cell.value instanceof Object) {
        const displayList = ['SYSML_BLOCKDEFINITION_KUAIJIEDIAN', 'SYSML_BLOCKDEFINITION_YUESUKUAIJIEDIAN', 'SYSML_REQUIREMENT_XQJD']

        const display = state.cell.value.getAttribute('display')

        if (displayList.some(i => i === display)) {
          const labelContainer = document.getElementsByClassName(`data-${state.cell.id}`)
          if (!labelContainer || !labelContainer.length) return
          let startHeight = 0
          const objectList = []
          for (const domItem of labelContainer[0].children) {
            if (domItem.tagName === 'DIV') {
              if (startHeight === 0) {

              } else {
                objectList.push({
                  top: startHeight,
                  dom: domItem
                })
              }
            }
            startHeight += domItem.clientHeight
          }
          const blockVisibleIcon = document.createElement('div')
          this.blockVisibleIcon = blockVisibleIcon
          blockVisibleIcon.style.border = '1px solid #000'
          blockVisibleIcon.style.position = 'absolute';
          blockVisibleIcon.style.left = (state.x - 30) + 'px';
          blockVisibleIcon.style.top = (state.y + 10) + 'px';
          blockVisibleIcon.innerHTML = `···`
          blockVisibleIcon.style.fontSize = '12px'
          blockVisibleIcon.style.fontWeight = '700'
          blockVisibleIcon.style.padding = '0 2px'
          blockVisibleIcon.style.lineHeight = '12px'
          graph.container.appendChild(blockVisibleIcon);
          this.redrawTools();

          blockVisibleIcon.addEventListener('click', mxUtils.bind(this, async function () {
            const util = new utils()
            await util.getBlockAttributeVisibleMap(state.cell, resolveCell(state.cell))

            const div = document.createElement('div');
            this.blockVisibleContainer = div
            div.className = 'geToolbarContainer geSidebarContainer geSidebar connectSelect';
            div.style.cssText = 'position:absolute;left:' + (state.x - 130) + 'px;top:' + (state.y + 7) +
              'px;padding: 0px;text-align:left;border:unset; box-shadow: rgb(209 209 209) 0px 0px 3px 1px;';

            state.cell.attributeVisibleMap.forEach((item, index) => {
              const node = document.createElement('div');
              node.style.cssText = 'padding: 5px 20px;font-size:12px;color: #000;line-height:14px;border-bottom:1px solid rgb(172 172 172);cursor: pointer;width:70px;white-space: nowrap; overflow: hidden;text-overflow: ellipsis;'
              node.innerText = item.group;
              node.title = item.group;
              if (item.visible === true || item.visible === 1) {
                node.style.color = 'green'
              }
              div.appendChild(node)
              node.addEventListener('click', function () {
                state.cell.attributeVisibleMap[index].visible = !state.cell.attributeVisibleMap[index].visible
                if (state.cell.attributeVisibleMap[index].visible) {
                  node.style.color = 'green'
                  node.style.fontWeight = '700'
                } else {
                  node.style.color = '#000'
                  node.style.fontWeight = '400'
                }

                util.upDataCellLableVisible(state.cell)
              })
            })
            this.redrawTools();
            graph.container.appendChild(div);
          }))
        }
      }
    }

    mxVertexToolHandler.prototype.createOtherIcon = function () {
      return
      const display = this.state.cell.getAttribute('display')

      const portDisplayList = ['SYSML_BLOCKDEFINITION_DAIYUESUFENQUKUAIJIEDIAN', 'SYSML_BLOCKDEFINITION_YUESUKUAIJIEDIAN', 'SYSML_BLOCKDEFINITION_BUJIAN', 'SYSML_BLOCKDEFINITION_KUAIJIEDIAN']

      if (portDisplayList.some(i => i === display)) {
        const connect = creatPort(this.state)
        this.domNode.appendChild(connect);
      }
    }

    mxVertexToolHandler.prototype.init = function () {

      mxVertexHandler.prototype.init.apply(this, arguments);
      if(window.zTreeObj?.currentSelectedNode?.type === 'mind_map') return

      // 选中更改颜色
      // updateStyle(this.state, true)
      this.domNode = document.createElement('div');
      this.domNode.style.position = 'absolute';
      this.domNode.style.whiteSpace = 'nowrap';
      this.domNode.style.display = 'flex';
      this.domNode.style.flexDirection = 'column';
      this.domNode.style.backgroundColor = '#fff';
      this.domNode.style.border = '1px solid #aaa';
      this.domNode.style.width = '30px';

      // Workaround for event redirection via image tag in quirks and IE8
      function createImage(src) {
        if (mxClient.IS_IE && !mxClient.IS_SVG) {
          var img = document.createElement('div');
          img.style.backgroundImage = 'url(' + src + ')';
          img.style.backgroundPosition = 'center';
          img.style.backgroundRepeat = 'no-repeat';
          img.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block';

          return img;
        } else {
          return mxUtils.createImage(src);
        }
      };
      if (myEditor.editor.graph.selectionCellsHandler.getHandledSelectionCells().length > 1) {
        return // 如果选中元素大于1，则不显示右侧快捷连线icon
      }
      // 创建其他图标
      this.createOtherIcon()

      // 创建连线图标
      this.createConnectIcons(this.state, this.graph, this)

      // 创建隐藏块元素属性图标
      this.createBlockVisibleIcon.call(this, this.state, this.graph)

      if (this.domNode && Array.isArray(Array.from(this.domNode.children)) && this.domNode.children.length) {
        this.graph.container.appendChild(this.domNode);

        this.redrawTools();
      }

    };

    mxVertexToolHandler.prototype.redraw = function () {
      mxVertexHandler.prototype.redraw.apply(this);
      this.redrawTools();
    };

    mxVertexToolHandler.prototype.redrawTools = function () {
      if (this.state != null) {
        const bgCell = window.myEditor.editor.graph.model.getCell('3');
        var dy = (mxClient.IS_VML && document.compatMode == 'CSS1Compat') ? 20 : 4;
        if (this.domNode != null) {
          this.domNode.style.left = (this.state.x + this.state.width + 10) + 'px';
          if ((bgCell.geometry.height - this.state.cell.geometry.y) >= this.domNode.childNodes.length * 23) {
            this.domNode.style.top = (this.state.y) + 'px';
          } else {
            this.domNode.style.top = (this.state.y - this.domNode.childNodes.length * 23 + (bgCell.geometry.height - this.state.cell.geometry.y - 2)) + 'px';
          }
        }

        if (this.blockVisibleIcon != null) {
          this.blockVisibleIcon.style.left = (this.state.x - 30) + 'px';
          this.blockVisibleIcon.style.top = (this.state.y) + 'px';
        }

        if (this.blockVisibleContainer != null) {
          /**
           * 如果元素距离画布边距过小，那么值属性框就到右侧显示
           * */
          if (this.state.cell.geometry.x < 120) {
            this.blockVisibleContainer.style.left = (this.state.x + this.state.width + 10) + 'px';
            this.blockVisibleIcon && this.blockVisibleIcon.parentNode && this.blockVisibleIcon.parentNode.removeChild(this.blockVisibleIcon);
            this.blockVisibleIcon = null;
          } else {
            this.blockVisibleContainer.style.left = (this.state.x - 120) + 'px';
          }

          if ((bgCell.geometry.height - this.state.cell.geometry.y) >=  this.blockVisibleContainer.childNodes.length * 25) {
            this.blockVisibleContainer.style.top = (this.state.y) + 'px';
          } else {
            this.blockVisibleContainer.style.top = (this.state.y - this.blockVisibleContainer.childNodes.length * 25 + (bgCell.geometry.height - this.state.cell.geometry.y)) + 'px';
          }

        }

      }
    };

    mxVertexToolHandler.prototype.destroy = function (sender, me) {
      mxVertexHandler.prototype.destroy.apply(this, arguments);
      // updateStyle(this.state, false)
      if (this.domNode != null) {
        this.domNode.parentNode && this.domNode.parentNode.removeChild(this.domNode);
        this.domNode = null;
      }
      if (this.blockVisibleIcon != null) {
        this.blockVisibleIcon && this.blockVisibleIcon.parentNode && this.blockVisibleIcon.parentNode.removeChild(this.blockVisibleIcon);
        this.blockVisibleIcon = null;
      }
      if (this.blockVisibleContainer != null) {
        this.blockVisibleContainer && this.blockVisibleContainer.parentNode && this.blockVisibleContainer.parentNode.removeChild(this.blockVisibleContainer);
        this.blockVisibleContainer = null;
      }
    };

    EditorUi.editor.graph.createHandler = function (state) {
      if (state != null &&
        this.model.isVertex(state.cell)) {
        return new mxVertexToolHandler(state);
      }

      return mxGraph.prototype.createHandler.apply(this, arguments);
    };
  }, 0)
}

var iconTolerance = 20;

// 自定义鼠标点击事件
function customItemClick(cells, ds, elt) {
  let oldMouseDown = ds.mouseDown;
  let oldMouseMove = ds.mouseMove;
  const graph = window.myEditor.editor.graph
  // 鼠标点击，端口自动加载
  if ("SYSML_BLOCKDEFINITION_WANZHENGPORTJIEDIAN" == cells[0].getAttribute('display')) {
    const parentCell = graph.getSelectionCell()
    if (!parentCell) return
  }
}

customItemClick.prototype.cancelMouseUp = (currentPoint, cells) => {
  return false
}
